一、spring框架介绍
spring用来管理javabean的框架,可以理解spring就是粘合剂,他可以将各个框架整合起来是分层的JAVAEE 轻量级的开源框架
好处:
- 解耦:程序员不需要创建管理对象,解除了对象管理和程序员之间的耦合
- AOP编程支持:spring支持面向切面编程,可以方便对程序进行拦截和监控
- 声明式事务:通过配置完成事务的管理,无需手动编程
- 方便程序的测试:spring支持junit4,完成程序测试
- 方便集成各个优秀的框架:mybatis ....
- 降低javaeeapi的使用:spring将难用的api进行封装。
核心功能:
IoC/DI 控制反转/依赖注入
AOP 面向切面编程
声明式事务.
二、SSM环境搭建
2.1. pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yh</groupId>
<artifactId>yh-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 集中定义依赖版本号 -->
<properties>
<junit.version>4.12</junit.version>
<spring.version>4.2.4.RELEASE</spring.version>
<mybatis.version>3.2.8</mybatis.version>
<mybatis.spring.version>1.2.2</mybatis.spring.version>
<mybatis.paginator.version>1.2.15</mybatis.paginator.version>
<mysql.version>5.1.32</mysql.version>
<slf4j.version>1.6.4</slf4j.version>
<jackson.version>2.4.2</jackson.version>
<druid.version>1.0.9</druid.version>
<httpclient.version>4.3.5</httpclient.version>
<jstl.version>1.2</jstl.version>
<servlet-api.version>2.5</servlet-api.version>
<jsp-api.version>2.0</jsp-api.version>
<joda-time.version>2.5</joda-time.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<commons-io.version>1.3.2</commons-io.version>
<commons-net.version>3.3</commons-net.version>
<pagehelper.version>3.7.5</pagehelper.version>
<jsqlparser.version>0.9.1</jsqlparser.version>
<commons-fileupload.version>1.3.1</commons-fileupload.version>
<jedis.version>2.7.2</jedis.version>
<solrj.version>4.10.3</solrj.version>
<dubbo.version>2.5.3</dubbo.version>
<zookeeper.version>3.4.7</zookeeper.version>
<zkclient.version>0.1</zkclient.version>
<activemq.version>5.11.2</activemq.version>
<freemarker.version>2.3.23</freemarker.version>
<quartz.version>2.2.2</quartz.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 时间操作组件 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
<!-- Apache工具组件 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>${commons-net.version}</version>
</dependency>
<!-- Jackson Json处理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<!-- quartz任务调度框架 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
<version>${mybatis.paginator.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- 文件上传组件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version>
</dependency>
<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<!-- solr客户端 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>${solrj.version}</version>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>${activemq.version}</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 资源文件拷贝插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>spring模块
| test | spring 提供测试功能 |
|---|---|
| Core Container | 核心容器.Spring 启动最基本的条件. |
| Beans | Spring 负责创建类对象并管理对象 |
| Core | 核心类 |
| Context | 上下文参数.获取外部资源或这管理注解等 |
| SpEl | expression.jar |
| AOP | 实现 aop 功能需要依赖 |
| Aspects | 切面 AOP 依赖的包 |
| Data Access/Integration | spring 封装数据访问层相关内容 |
| JDBC | Spring 对 JDBC 封装后的代码. |
| ORM | 封装了持久层框架的代码.例如 Hibernate |
| transactions | 对应 spring-tx.jar,声明式事务使用. |
| WEB | 需要 spring 完成 web 相关功能时需要. |
2.2 配置文件
sqlMapConfig
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEconfiguration
PUBLIC"-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>dao层配置
db.properties 数据库连接信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/hg?characterEncoding=utf-8
jdbc.username=root
jdbc.password=rootapplicationContext-dao.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 数据库连接池 -->
<!-- 加载配置文件 -->
<context:property-placeholderlocation="classpath:properties/*.properties"/>
<!-- 数据库连接池 -->
<beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
<propertyname="driverClassName"value="${jdbc.driver}"/>
<propertyname="maxActive"value="10"/>
<propertyname="minIdle"value="5"/>
</bean>
<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<propertyname="dataSource"ref="dataSource"/>
<!-- 加载mybatis的全局配置文件 -->
<propertyname="configLocation"value="classpath:mybatis/SqlMapConfig.xml"/>
</bean>
<beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer">
<propertyname="basePackage"value="com.hg.mapper"/>
</bean>
</beans>Service层
applicationContext-service.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 包扫描器,扫描带@Service注解的类 -->
<context:component-scan base-package="com.hg.service"></context:component-scan>
</beans>applicationContext-trans.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 事务管理器 -->
<beanid="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源 -->
<propertyname="dataSource"ref="dataSource"/>
</bean>
<!-- 开启事务注解驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 通知 -->
<tx:adviceid="txAdvice"transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:methodname="save*"propagation="REQUIRED"/>
<tx:methodname="insert*"propagation="REQUIRED"/>
<tx:methodname="add*"propagation="REQUIRED"/>
<tx:methodname="create*"propagation="REQUIRED"/>
<tx:methodname="delete*"propagation="REQUIRED"/>
<tx:methodname="update*"propagation="REQUIRED"/>
<tx:methodname="find*"propagation="SUPPORTS"read-only="true"/>
<tx:methodname="select*"propagation="SUPPORTS"read-only="true"/>
<tx:methodname="get*"propagation="SUPPORTS"read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:advisoradvice-ref="txAdvice"
pointcut="execution(* com.hg.service.*.*(..))"/>
</aop:config>
</beans>REQUIRED 如果有事务,就在当前事务里执行,没有则开启新事务。必须在事务中执行。SUPPORTS当前有事务就在当前事务中执行,没有则不开启事务
controller层
配置springmvc
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置包扫描器 -->
<context:component-scan base-package="com.hg.controller"></context:component-scan>
<!-- 配置注解驱动 -->
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"value="/WEB-INF/jsp/"/>
<property name="suffix"value=".jsp"/>
</bean>
</beans>web.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="hg"version="2.5">
<display-name>hg-manager</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 初始化spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- springmvc的前端控制器 -->
<servlet>
<servlet-name>hg-manager</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hg-manager</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app><load-on-startup>1</load-on-startup>初始化tomcat web容器时,即初始化spring容器。否则第一次访问时才初始化。
<url-pattern>/</url-pattern>静态资源会被拦截。
三、基础知识
3.1 spring创建对象
<!-- 创建对象并赋值 -->
<!--
id:表示获取到对象的标识
class:创建哪个类的对象(全路径)
作用域
singleton:默认值 一个bean对应一个实例对象
prototype:一个bean对应多个实例对象
request:在一个请求中,一个bean定义对应一个实例
session: 在一个http session中,一个bean对应一个实例
qlobal session:在一个全局http session中,一个bean对应一个实例
request session qlobal session 旨在web的配置文件中有效
bean的生命周期
首先在类中创建初始化和销毁方法,然后在配置时添加init-method和destory-method方法
-->
<bean id="" class="" init-method="init初始化方法" destroy-method="destory销毁方法">
<!-- 为构造方法中的参数赋值 -->
<constructor-arg index="0" name="id" type="int" value="123"></constructor-arg>
</bean>
<!-- 通过实例工厂创建对象 -->
<bean id="factory"class="com.bjsxt.pojo.PeopleFactory"></bean>
<!--
factory-bean:工厂类
factory-method:工厂类中的方法名
-->
<bean id="peo1" factory-bean="factory" factory-method="newInstance"></bean>
<!-- 通过静态工厂创建对象 -->
<bean id="peo2" class="com.bjsxt.pojo.PeopleFactory" factory-method="newInstance"></bean>
<!-- 对象赋值 -->
<!-- 通过构造方法注入 -->
<bean id="peo" class="com.bjsxt.pojo.People">
<!-- 为构造方法中的参数赋值 -->
<constructor-arg index="0" name="id" type="int" value="123"></constructor-arg>
</bean>
<!-- 通过属性set方法注入 -->
<!--如果属性是基本数据类型或 String 等简单-->
<bean id="peo" class="com.bjsxt.pojo.People">
<property name="id" value="222"></property>
<property name="name" value="张三"></property>
</bean>
<!--等效于-->
<bean id="peo" class="com.bjsxt.pojo.People">
<property name="id">
<value>456</value>
</property>
<property name="name">
<value>zhangsan</value>
</property>
</bean>
<!--set-->
<property name="sets">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</set>
</property>
<!--list-->
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<!--list中只有一个值时-->
<property name="list" value="1"> </property>
<property name="strs" >
<array>
<value>1</value>
<value>2</value>
<value>3</value>
</array>
</property>
<!--map-->
<property name="map">
<map>
<entry key="a" value="b" >
</entry> <entry key="c" value="d" >
</entry>
</map>
</property>
<!--Properties-->
<property name="demo">
<props>
<prop key="key">value</prop>
<prop key="key1">value1</prop>
</props>
</property>
<!--P命名空间-->
<!-- 首先声明p命名空间,即添加 xmlns:p="http://www.springframework.org/schema/p" -->
<bean id="" class="" p:属性名="基本数据类型" p:属性名-ref="对象类型"></bean>
<!--对象类型,依赖注入,将一个实例对象作为另一个对象的参数-->
<bean id="peo" class="com.bjsxt.pojo.People">
<property name="desk" ref="desk"></property>
</bean>
<bean id="desk" class="com.bjsxt.pojo.Desk">
<property name="id" value="1"></property>
<property name="price" value="12"></property>
</bean>3.2 类后置处理器(对所有类增强)
package com.note.technology.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @Classname BeanPostProcessorDemo
* @Description 对所有类增强的方法
*/
@Component
public class BeanPostProcessorDemo implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return null;
}
}3.3 获取spring中的对象
// BeanFactory和ApplicationContext区别:
// app是bean的子接口,加载配置文件所用的方法不同,bean可以实现延迟加载,app不能
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = ac.getBean("peo",People.class);
System.out.println(people);3.4 AOP
概念
在原有纵向执行流程中添加横切面 ,不需要修改原有程序代码 ,具有高扩展性。
连接点 目标对象中所有可以被增强的方法 原有功能 切点, pointcut 通知 增强的功能的方法
前置通知: 在切点之前执行的功能.before advice
后置通知: 在切点之后执行的功能,after advice
如果切点执行过程中出现异常,会触发异常通知.throws advice目标对象 被代理的对象 切面. 所有功能总称 织入 把切面嵌入到原有功能的过程 代理 将通知织入到目标对象,行城的就是代理对象 Schema-based实现AOP
java// 创建前置通知类 public class MyBeforeAdvice implements MethodBeforeAdvice { //arg0: 切点方法对象 Method 对象 //arg1: 切点方法参数 //arg2:切点在哪个对象中 @Override public void before(Method arg0, Object[] arg1, Objectarg2) throws Throwable { System.out.println("执行前置通知"); } } // 创建后置通知类 public class MyAfterAdvice implements AfterReturningAdvice { //arg0: 切点方法返回值 //arg1:切点方法对象 //arg2:切点方法参数 //arg3:切点方法所在类的对象 @Override public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { System.out.println("执行后置通知"); } } // 创建异常通知类 //新建一个类实现 throwsAdvice 接口 //必须自己写方法,且必须叫 afterThrowing //有两种参数方式 必须是 1 个或 4 个异常类型要与切点报的异常类型一致 public class MyThrow implements ThrowsAdvice{ // public void afterThrowing(Method m, Object[] args, Object target, Exception ex) { // System.out.println("执行异常通知"); // } public void afterThrowing(Exception ex) throws Throwable { System.out.println("执行异常通过-schema-base 方式 "); } } // 创建环绕通知类 public class MyArround implements MethodInterceptor { @Override public Object invoke(MethodInvocation arg0) throws Throwable { System.out.println("环绕-前置"); Object result = arg0.proceed(); //放行,调用切点方式 System.out.println("环绕-后置"); return result; } }xml<!-- Schema-based方式通知配置 --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/sc hema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop. xsd"> <!-- 配置通知类对象,在切面中引入 --> <bean id="mybefore" class="com.bjsxt.advice.MyBeforeAdvice"></bean> <bean id="myafter" class="com.bjsxt.advice.MyAfterAdvice"></bean> <bean id="mythrow" class="com.bjsxt.advice.MyThrow"></bean> <bean id="myarround" class="com.bjsxt.advice.MyArround"></bean> <!-- 配置切面 --> <aop:config> <!-- 配置切点 --> <!-- * 通配符,匹配任意方法名,任意类名,任意一级包名 如果希望匹配任意方法参数 (..) --> <aop:pointcut expression="execution(* com.bjsxt.test.Demo.demo2())" id="mypoint"/> <!-- 通知 --> <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/> <aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/> <aop:advisor advice-ref="mythrow" pointcut-ref="mypoint" /> <aop:advisor advice-ref="myarround" pointcut-ref="mypoint" /> </aop:config> <!-- 配置 Demo 类,测试使用 --> <bean id="demo" class="com.bjsxt.test.Demo"></bean> </beans>AspectJ 方式
java//新建类,在类写任意名称的方法 public class MyThrowAdvice{ public void myexception(Exception e1){ System.out.println("执行异常通知 "+e1.getMessage()); } }xml<!--<aop:aspect>的 ref 属性表示:方法在哪个类中.--> <!--<aop: xxxx/> 表示什么通知--> <!--method: 当触发这个通知时,调用哪个方法--> <!--throwing: 异常对象名,必须和通知中方法参数名相同(可 以不在通知中声明异常对象)--> <bean id="mythrow" class="com.bjsxt.advice.MyThrowAdvice"></bean> <aop:config> <aop:aspect ref="mythrow"> <aop:pointcut expression="execution(* com.bjsxt.test.Demo.demo1())" id="mypoint"/> <aop:after-throwing method="myexception" pointcut-ref="mypoint" throwing="e1"/> </aop:aspect> </aop:config> <bean id="demo" class="com.bjsxt.test.Demo"></bean> <!-- <aop:after/> 后置通知,是否出现异常都执行 <aop:after-returing/> 后置通知,只有当切点正确执行时 执行 <aop:after/> 和 <aop:after-returing/> 和 <aop:after-throwing/>执行顺序和配置顺序有关 execution() 括号不能扩上 args 中间使用 and 不能使用&& 由 spring 把 and 解析成&& args(名称) 名称自定义的.顺序和 demo1(参数,参数)对应 <aop:before/> arg-names=” 名 称 ” 名 称 来 源 于 expression=”” 中 args(),名称必须一样 args() 有几个参数,arg-names 里面必须有几个参数 arg-names=”” 里面名称必须和通知方法参数名对应 -->Schema-based和AspectJ 方式区别
- chema-based方式需要新建一个类并实现接口 AspectJ方式是在一个类中直接添加方法,不用实现接口
- Schema-based配置时用的同一个标签 AspectJ不同的通知使用不同的标签
注解方式(基于Aspect)
xml<!-- 添加扫描注解的包路径配置 --> <context:component-scan base-package="com.bjsxt.advice"></context:component-scan>java// 切点配置类 //在 切点注解类中添加@Componet //在方法上添加@Pointcut(“”) 定义切点 // @Component相当于<bean/> 如果没有参数,把类名首字母变小写,相当于<bean id=""/> @Component(“自定义名称”) @Component public class Demo { @Pointcut("execution(* com.bjsxt.test.Demo.demo1())") public void demo1() throws Exception{ // int i = 5/0; System.out.println("demo1"); } }java// 通知配置类 //@Component 类被 spring 管理 //@Aspect 相当于<aop:aspect/>表示通知方法在当前类中 @Component @Aspect public class MyAdvice { @Before("com.bjsxt.test.Demo.demo1()") public void mybefore(){ System.out.println("前置"); } @After("com.bjsxt.test.Demo.demo1()") public void myafter(){ System.out.println("后置通知"); } @AfterThrowing("com.bjsxt.test.Demo.demo1()") public void mythrow(){ System.out.println("异常通知"); } @Around("com.bjsxt.test.Demo.demo1()") public Object myarround(ProceedingJoinPoint p) throws Throwable{ System.out.println("环绕-前置"); Object result = p.proceed(); System.out.println("环绕-后置"); return result; } }
3.5 声明式事务
<context:property-placeholder location="classpath:db.properties,classpath:second.pr operties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverMa nagerDataSource">
<property name="driverClassName" value="${jdbc.driver}">
</property> <property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- spring-jdbc.jar 中 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSour ceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置声明式事务 -->
<tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes>
<!-- 哪些方法需要有事务控制 -->
<!-- 方法以 ins 开头事务管理 -->
<tx:method name="ins*" />
<tx:method name="del*" />
<tx:method name="upd*" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 切点范围设置大一些 -->
<aop:pointcut expression="execution(* com.bjsxt.service.impl.*.*(..))" id="mypoint" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint" /> </aop:config>
<!-- <tx:method />中的属性解释 -- >
<!--
name:哪些方法需要有事务控制 ,支持*通配符
readonly
如果为 true,告诉数据库此事务为只读事务.数据化优化,会对性能有一定提升,所以只要是查询的方法,建议使用此数据如果为
false(默认值),事务需要提交的事务.建议新增,删除,修改
propagation:控制事务传播行为,当一个具有事务控制的方法被另一个有事务控制的方法调用后,选择如何管理事务
取值:
REQUIRED (默认值) 如果当前有事务,就在事务中执行,如果当前没有事务,新建一个事务
SUPPORTS 如果当前有事务就在事务中执行,如果当前没有事务,就在非事务状态下执行
MANDATORY 必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错
REQUIRES_NEW 必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,把当前事务挂起
NOT_SUPPORTED 必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前事务挂起
NEVER 必须在非事务状态下执行,如果当前没有事务,正常执行, 如果当前有事务,报错
NESTED 必须在事务状态下执行.如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务
isolation 事务隔离级别 在多线程或并发访问下如何保证访问到的数据具有完整性的
取值
DEFAULT 默认值,由底层数据库自动判断应该使用什么隔离级别
READ_UNCOMMITTED 可以读取未提交数据,可能出现脏读,不重复读,幻读,效率最高
READ_COMMITTED 只能读取其他事务已提交数据.可以防止脏读,可能出现不可重复读和幻读
REPEATABLE_READ 读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读.脏读,可能出现幻读
SERIALIZABLE 排队操作,对整个表添加锁.一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表,是最安全的,也是效率最低的
rollback-for 当出现什么异常时需要进行回滚,建议给定该属性值,虽然有默认的值,取值是异常类型全限定路径.手动抛异常一定要给该属性值.
no-rollback-for 当出现什么异常时不滚回事务
-->3.6 代理方式&自动注入
控制spring使用代理的方式
xml//设置为 true 使用 cglib //设置为 false 使用 jdk(默认值) <aop:aspectj-autoproxy proxy-target-class="true"> </aop:aspectj-autoproxy>自动注入
在 Spring 配置文件中对象名和 ref=”id”id 名相同使用自动注入,可以 不配置<property/> 两种配置办法 在<bean>中通过 autowire=”” 配置,只对这个<bean>生效 在<beans>中通过 default-autowire=””配置,表当当前文件中所 有<bean>都是全局配置内容 autowire取值: default: 默认值,根据全局 default-autowire=””值.默认全局和局 部都没有配置情况下,相当于 no no: 不自动注入 byName: 通过名称自动注入.在 Spring 容器中找类的 Id byType: 根据类型注入.spring 容器中不可以出现两个相同类型的<bean> constructor: 根据构造方法注入.提供对应参数的构造方法(构造方法参数中包含注入对 戏那个) 底层使用 byName, 构造方法参数名和其他<bean>的 id 相同
3.7 加载配置文件
在 src 下新建 xxx.properties 文件
在 spring 配置文件中先引入 xmlns:context,在下面添加
xml<!-- 如果需要记载多个配置文件逗号分割 ,也可使用通配符 * --> <context:property-placeholder location="classpath:db.properties"/>添加了属性文件记载,并且在
<beans>中开启自动注入注意的地方SqlSessionFactoryBean 的 id 不能叫做 sqlSessionFactory
把原来通过ref引用替换成value赋值,自动注入只能影响 ref,不会影响 value 赋值
xml<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.bjsxt.mapper"></property> <property name="sqlSessionFactoryBeanName" value="factory"></property> </bean>
在被Spring管理的类中通过@Value(“${key}”)取出properties中内容
xml<context:component-scan base-package="com.bjsxt.service.impl"></context:compo nent-scan>java//key 和变量名可以不相同 //变量类型任意,只要保证 key 对应的 value 能转换成这个 类型就可以. @Value("${my.demo}") private String test;
3.8 spring常用注解
@Component //创建类对象,相当于配置<bean/>
@Service //与@Component 功能相同.写在 ServiceImpl 类上.
@Repository //与@Component 功能相同. 写在数据访问层类上.
@Controller //与@Component 功能相同. 写在控制器类上.
@Resource(不需要写对象的 get/set) //java 中的注解 默认按照 byName 注入,如果没有名称对象,按照 byType 注入 建议把对象名称和 spring 容器中对象名相同
@Autowired(不需要写对象的 get/set)
@Qualifier()// spring 的注解 默认按照 byType 注入.
@Value() //获取 properties 文件中内容
@Pointcut() //定义切点
@Aspect() //定义切面类
@Before() //前置通知
@After //后置通知
@AfterReturning //后置通知,必须切点正确执行
@AfterThrowing //异常通知
@Arround//环绕通知